/*

 */
package com.ohos.connect.devicecloud.iot.modular.device.task;

import com.google.gson.Gson;
import com.ohos.connect.devicecloud.app.api.ProjectDeviceApi;
import com.ohos.connect.devicecloud.common.timer.CommonTimerTaskRunner;
import com.ohos.connect.devicecloud.iot.modular.device.service.DeviceService;
import com.ohos.connect.devicecloud.mqtt.api.MqttApi;

import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

/**
 * 设备状态定时任务
 *
 * @author mzq
 */
@Slf4j
@Component
public class DeviceRedisStatusTaskRunner implements CommonTimerTaskRunner {
    @Autowired
    private DeviceService deviceService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private ProjectDeviceApi projectDeviceApi;
    @Resource
    private MqttApi mqttApi;
    @Value("${iot.redis.prefix}")
    private String IOT_REDIS_PREFIX = "iot";

    @Override
    public void action() {
        Map<String, Map<String,String>> iotKeyValues = getIotKeyValues();
        iotKeyValues.forEach((key, value) -> {
            String devId = key.substring(IOT_REDIS_PREFIX.length());
            String heartBeat = value.get("heartBeat");
            long currentTime = System.currentTimeMillis();
            // 减少更新频率，200秒没有心跳数据则认为设备已经离线，更新数据库字段
            if (StringUtils.isEmpty(heartBeat) || currentTime - Long.parseLong(heartBeat) > 150 * 1000) {
                // 设备已经离线
                // 将设备离线信息放到缓存中
                redisTemplate.boundHashOps(IOT_REDIS_PREFIX + devId).put("status", "offline");
                try {
                    deviceOnlineNotice("", devId);
                } catch (Exception e) {
                }
            }
        });
    }

    public Map<String, Map<String,String>> getIotKeyValues() {
        Map<String, Map<String,String>> result = new HashMap<>();
        // 构建扫描选项：匹配前缀"iot*"，每次扫描100条
        ScanOptions options = ScanOptions.scanOptions()
            .match("iot*")
            .count(100)
            .build();
        try (Cursor<byte[]> cursor = redisTemplate.getConnectionFactory().getConnection().scan(options)) {
            //  遍历游标，获取键和值
            while (cursor.hasNext()) {
                // 获取键（字节数组转字符串）
                byte[] keyBytes = cursor.next();
                String key = new String(keyBytes);
                // 根据实际数据类型获取值
                String status = (String) redisTemplate.boundHashOps(key).get("status");
                String heartBeat = (String) redisTemplate.boundHashOps(key).get("heartBeat");
                if (StringUtils.isNotBlank(status) && StringUtils.isNotBlank(heartBeat) && "online".equals(status)) {
                    Map<String, String> deviceMap = new HashMap<>();
                    deviceMap.put("heartBeat", heartBeat);
                    result.put(key, deviceMap);
                }
            }
        } catch (Exception e) {
            log.error("获取键值出错: {}", e.getMessage());
        }
        return result;
    }

    // 向APP发送设备在线通知   网关id预留
    private void deviceOnlineNotice(String gatewayId, String devId) {
        String topic = "/user/" + getDeviceUserAccount(devId) + "/signaltrans/v1/categories/data";
        // 构造header
        JSONObject header = new JSONObject();
        header.put("timestamp", Long.toString(System.currentTimeMillis()));
        header.put("category", "device");
        header.put("notifyType", "deviceStatus");
        // 构造body
        JSONObject body = new JSONObject();
        body.put("devId", devId);
        body.put("gatewayId", gatewayId);
        body.put("status", "offline");
        JSONObject payload = new JSONObject();
        payload.put("header", header);
        payload.put("body", body);
        // 使用Gson将对象序列化为JSON字符串
        Gson gson = new Gson();
        String jsonPayload = gson.toJson(payload);
        // 创建MqttMessage并设置其内容
        MqttMessage message = new MqttMessage(jsonPayload.getBytes());
        try {
            mqttApi.sendMqttMessage(topic, message);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private String getDeviceUserAccount(String deviceId) {
        return projectDeviceApi.getUserAccountByDeviceId(deviceId);
    }

}
